package modbus

import (
	"errors"
	"fmt"

	"gitee.com/lossage/simplego/io"
	"gitee.com/lossage/simplego/math/crc"
	"gitee.com/lossage/simplego/strings"
)

type ModbusRTU struct {
	FrameListener
	modbusAction IModbusAction
	tcpClient    io.IConnectionClient
}

func CreateModbusRTU(comName string, baudRate, dataBits, stopBits, parity, timeOutMilsecond int, autoReconnect bool) (IModbusTask, error) {
	var err error
	res := new(ModbusRTU)
	res.modbusAction = CreateModbusAction()
	res.tcpClient, err = io.CreateCommClient(comName, baudRate, dataBits, stopBits, parity, timeOutMilsecond, true)
	if err != nil {
		return nil, err
	}
	return res, res.tcpClient.Connect()
}

func (_this *ModbusRTU) ReadOnce(adress, command uint8, startReg uint16, regLen uint8, datas []uint16) (*ModbusModel, *ModbusModel, error) {
	if _this.tcpClient == nil {
		return &_this.modbusAction.GetReceiveFrame().ModbusModel, &_this.modbusAction.GetSendFrame().ModbusModel, errors.New("tcp连接为空")
	}
	if _this.tcpClient.IsConnecting() {
		return &_this.modbusAction.GetReceiveFrame().ModbusModel, &_this.modbusAction.GetSendFrame().ModbusModel, errors.New("正在连接中")
	}
	writer := func(buffer []byte) error {
		buffer = crc.Crc16Add(buffer)
		fmt.Println("send:" + strings.ArrayToHexString(buffer))
		if _this.senderEvent != nil {
			_this.senderEvent.Event(buffer)
		}
		return _this.tcpClient.Write(buffer)
	}
	reader := func() ([]byte, error) {
		buffer, err := _this.tcpClient.Read()
		if err != nil {
			return nil, err
		}
		if _this.receiverEvent != nil {
			_this.receiverEvent.Event(buffer)
		}
		if !crc.Crc16Check(buffer) {
			return nil, errors.New("crc校验失败")
		}
		fmt.Println("receive:" + strings.ArrayToHexString(buffer))
		return buffer[:len(buffer)-2], nil
	}
	_this.modbusAction.SetWriter(&writer)
	_this.modbusAction.SetReader(&reader)
	err := _this.modbusAction.ReadOnce(adress, command, startReg, regLen)
	return &_this.modbusAction.GetReceiveFrame().ModbusModel, &_this.modbusAction.GetSendFrame().ModbusModel, err
}
